#include "app.h"
#include "util.h"
#include <uis.h>
#include <apps.h>
#include "../dbg/dbg.h"

// TODO: set previous state here
#define BACK_STATE			NEWAPP_STATE_MAIN
#define UPDATE_TIMER_ID		99


// -----------------------------------------------------------------------------------------
// Local constants

static const WCHAR		str_text[] = {'P','r','o','g','r','e','s','s','B','a','r',0};
static const WCHAR		str_loading[] = {'L','o','a','d','i','n','g','.','.','.',0};
static const WCHAR		str_percent[] = {'%', 0};


// -----------------------------------------------------------------------------------------
// Local functions

static UINT32 HandleDone( EVENT_STACK_T * ev_st, void * app );
static UINT32 HandleCancel( EVENT_STACK_T * ev_st, void * app );

static UINT32 HandleNext( EVENT_STACK_T * ev_st, void * app );
static UINT32 HandlePrev( EVENT_STACK_T * ev_st, void * app );

static UINT32 HandleTimerExpired( EVENT_STACK_T * ev_st, void * app );


static UINT32 APP_UtilSetProgressPercent( EVENT_STACK_T * ev_st, void * app, UINT8 percent );
static UINT32 APP_UtilAddEvSetProgressPercent( EVENT_STACK_T * ev_st, void * app, UINT8 percent );
static UINT32 APP_UtilAddEvSetProgressString( EVENT_STACK_T * ev_st, void * app, WCHAR * str );
static UINT32 APP_UtilAddEvSetProgressValueString( EVENT_STACK_T * ev_st, void * app, WCHAR * value_str );


// -----------------------------------------------------------------------------------------
// Global handlers array

const EVENT_HANDLER_ENTRY_T progress_state_handlers[] =
{
	{ EV_DIALOG_DONE,			HandleCancel },
   	{ EV_DONE,					HandleDone },		// Pressing "done" key
	
	{ EV_NEXT,					HandleNext },		// keypress UP
	{ EV_PREV,					HandlePrev },		// keypress DOWN
	
	{ EV_TIMER_EXPIRED,			HandleTimerExpired },

	{ STATE_HANDLERS_END,		NULL }
};

// -----------------------------------------------------------------------------------------
// Global enter/exit state functions

UINT32 ProgressStateEnter( EVENT_STACK_T * ev_st, void * app, ENTER_STATE_TYPE_T type )
{
	NEWAPP_T *		papp = newapp(app);
	SU_PORT_T		port = papp->apt.port;
	UIS_DIALOG_T	dialog;
	CONTENT_T		cnt;
	UINT32			status;
	ACTIONS_T		action_list;
	
	dbg("ProgressStateEnter: Enter, type = %d", type);
	if ( type != ENTER_STATE_ENTER )
		return RESULT_OK;
	
	// TODO: add your code here
	papp->percent = 0;
	
	status = UIS_MakeContentFromString( "q0", &cnt, str_text );
	dbg("ProgressStateEnter: UIS_MakeContentFromString DONE, status = %d", status);
	
	if ( status != RESULT_OK )
		return status;
	
	action_list.count = 0;	// Init
	ActionAdd(&action_list, EV_DONE, RES_ACTION_DONE);
	
	dialog = UIS_CreateProgressBar( &port,
								0,				// some picture
								&cnt,			// title content
								str_loading,	// string
								papp->percent,	// value
								FALSE,			// has arrows
								str_percent,	// value str
								&action_list,
								0 );
	dbg("ProgressStateEnter: UIS_CreateProgressBar DONE, dialog = %d", dialog);
	
	if ( dialog == 0 )
		return RESULT_FAIL;
	papp->apt.dialog = dialog;
	
	APP_UtilStartCyclicalTimer( 200, UPDATE_TIMER_ID, app );
	
	dbg("ProgressStateEnter: END", 0);
	return RESULT_OK;
}

UINT32 ProgressStateExit( EVENT_STACK_T * ev_st, void * app, EXIT_STATE_TYPE_T type )
{
	NEWAPP_T *		papp = newapp(app);
	UINT32			status;
	
	dbg("ProgressStateExit: Enter, type = %d", type);
	if ( type != EXIT_STATE_EXIT )
		return RESULT_OK;
	
	APP_UtilStopTimer( app );
	
	status = APP_UtilUISDialogDelete( &papp->apt.dialog );
	
	dbg("ProgressStateExit: END, status = %d", status);
	return status;
}


// -----------------------------------------------------------------------------------------
// Other local functions

UINT32 HandleDone( EVENT_STACK_T * ev_st, void * app )
{
	NEWAPP_T *		papp = newapp(app);
	UINT32			status;
	
	dbg("HandleDone: Enter", 0);
	APP_ConsumeEv(ev_st, app);
	
	// Pressing "back" key
	// TODO: add your code here
	
	status = APP_UtilChangeState( BACK_STATE, ev_st, app );
	dbg("HandleDone: END, status = %d", status);
	return status;
}

UINT32 HandleCancel( EVENT_STACK_T * ev_st, void * app )
{
	dbg("HandleCancel: Enter", 0);
	APP_ConsumeEv(ev_st, app);
	
	APP_UtilStopTimer( app );
	
	return RESULT_OK;
//	return ELF_Exit( ev_st, app );
}

UINT32 HandleNext( EVENT_STACK_T * ev_st, void * app )
{
	NEWAPP_T *		papp = newapp(app);
	
	dbg("HandleNext: Enter", 0);
	APP_ConsumeEv(ev_st, app);
	
	if ( papp->percent < 100 )
		papp->percent++;
	
	dbg("HandleNext: %d %%", papp->percent);
	APP_UtilSetProgressPercent( ev_st, app, papp->percent );
	
	dbg("HandleNext: END", 0);
	return RESULT_OK;
}

UINT32 HandlePrev( EVENT_STACK_T * ev_st, void * app )
{
	NEWAPP_T *		papp = newapp(app);
	
	dbg("HandlePrev: Enter", 0);
	APP_ConsumeEv(ev_st, app);
	
	if ( papp->percent > 0 )
		papp->percent--;
	
	dbg("HandlePrev: %d %%", papp->percent);
	APP_UtilSetProgressPercent( ev_st, app, papp->percent );
	
	dbg("HandlePrev: END", 0);
	return RESULT_OK;
}

UINT32 HandleTimerExpired( EVENT_STACK_T * ev_st, void * app )
{
	NEWAPP_T *		papp = newapp(app);
	
	dbg("HandleTimerExpired: Enter", 0);
	APP_ConsumeEv(ev_st, app);
	if ( papp->percent < 100 )
		papp->percent++;
	
	APP_UtilSetProgressPercent( ev_st, app, papp->percent );
	
	dbg("HandleTimerExpired: END", 0);
	return RESULT_OK;
}



// -----------------------------------------------------------------------------------------
// Util

UINT32 APP_UtilSetProgressPercent( EVENT_STACK_T * ev_st, void * app, UINT8 percent )
{
	WCHAR		unicode_str[16];
	char		str[16];
	UINT32		status;
	sprintf( str, "%d %%", percent );
	u_atou(str, unicode_str);
	
	status = APP_UtilAddEvSetProgressPercent( ev_st, app, percent );
	if ( status == RESULT_OK )
		status = APP_UtilAddEvSetProgressValueString( ev_st, app, unicode_str );
	if ( status == RESULT_OK )
		status = UIS_HandleEvent( ((APPLICATION_T *)(app))->dialog, ev_st );
	return status;
}

UINT32 APP_UtilAddEvSetProgressPercent( EVENT_STACK_T * ev_st, void * app, UINT8 percent )
{
	ADD_EVENT_DATA_T	add;
	add.data.val_dword = percent;
	return AFW_AddEvEvD( ev_st, EV_PB_SET_PERCENT, &add );
}
UINT32 APP_UtilAddEvSetProgressString( EVENT_STACK_T * ev_st, void * app, WCHAR * str )
{
	ADD_EVENT_DATA_T	add;
	add.data.val_ptr = str;
	return AFW_AddEvEvD( ev_st, EV_PB_SET_STR, &add );
}
UINT32 APP_UtilAddEvSetProgressValueString( EVENT_STACK_T * ev_st, void * app, WCHAR * value_str )
{
	ADD_EVENT_DATA_T	add;
	add.data.val_ptr = value_str;
	return AFW_AddEvEvD( ev_st, EV_PB_SET_VALUE_STR, &add );
}

